#include <iostream>
#include <unistd.h>
#include <string>
#include <cstring>
#include <cstdlib>      // stdlib.h
#include <sys/wait.h>
#include <sys/types.h>

#define N 2
#define NUM 1024

using namespace std;

void Read(int rid)
{
    char buffer[NUM];
    int cnt = 0;

    while(true)
    {
        buffer[0] = 0;
        // read返回读取到的数据个数
        // 用sizeof是因为可以识别到\0，所以buffer长度为NUM
        // 如果用strlen，那么buffer长度为0
        ssize_t n = read(rid,buffer,sizeof(buffer));
        if(n > 0)
        {
            buffer[n] = 0;      // 0 == '\0'
            cout << "father get a message[" << getpid() << "]# " << buffer << endl;
        }
        else if(n == 0)
        {
            printf("father read file done!\n");
            break;
        }
        else
            break;

        cnt++;
        if(cnt > 5)break;
        // cout << "n: " << n << endl; 

    }
}
void Write(int wid)
{
    char buffer[NUM];
    string str = "hello, I am child";
    int id = getpid();
    int num = 0;
    int cnt = 0;

    while(true)
    {
        sleep(1);

        // 构建发送字符串
        buffer[0] = 0;      // 字符串清空，是为了提醒阅读代码的人，把这个数组当作字符串了
        snprintf(buffer,sizeof(buffer),"%s-%d-%d",str.c_str(),id,num++);
        // cout << buffer << endl;

        // 发送给父进程/写入两个进程的共同缓冲区
        write(wid,buffer,strlen(buffer));
        // sleep(5);

        // close(wid);

        // char c = 'c';
        // write(wid,&c,1);
        // num++;
        // cout << num << endl;

        if(cnt >= 5)
            break;

    }

}
int main()
{
    int pipefd[2] = {0};
    int n = pipe(pipefd);
    if(n < 0)
        return 1;
    
    // cout << "pipefd[0]:" << pipefd[0] << "\npipefd[1]:" << pipefd[1] << endl;

    // 由子进程写入，父进程读取
    pid_t id = fork();
    if(id < 0)
        return 2;
    else if(id == 0)
    {
        // 子进程
        close(pipefd[0]);
        Write(pipefd[1]);
        
        // close(pipefd[1]);
        exit(0);
    }
    else if(id > 0)
    {
        // 父进程
        close(pipefd[1]);
        Read(pipefd[0]);
        close(pipefd[0]);

        cout << "father close read fd: " << pipefd[0] << endl;
        sleep(3);

        int status = 0;
        pid_t rid = waitpid(id,&status,0);
        if(rid < 0)return 3;

        // 返回的状态码为SIGPIPE
        // 读端关闭，写端正常写入，操作系统就要杀掉正在写入的进程，同时会收到13(SIGPIPE)信号
        
        // 子进程被信号杀掉时，status的比特位
        // 低7位表示导致子进程终止的信号编号
        // 第8位表示子进程在终止时是否产生了核心转储
        cout << "wait child success: " << rid << " exit code: " << ((status >> 8)&0xFF) << " exit signal: " << (status & 0x7F) << endl;

        sleep(3);
        cout << "father quit" << endl;
    }

    return 0;
}
